package com.md.application.service.logs;

import com.google.common.collect.Maps;
import com.md.api.LogsApi;
import com.md.api.OpenLogsApi;
import com.md.application.assembler.LogsAssembler;
import com.md.base.exception.ServerException;
import com.md.client.OpenApiClient;
import com.md.domain.model.bo.QueryLogsBO;
import com.md.domain.model.po.Logs;
import com.md.domain.service.LogsDomainService;
import com.md.infrastructure.client.SystemClient;
import com.md.infrastructure.persistence.repository.LogsRepository;
import com.md.infrastructure.value.ErrorEnum;
import com.md.model.page.PageResponse;
import com.md.model.system.CommonResult;
import com.md.request.OperationLogsRequest;
import com.md.request.QueryLogsRequest;
import com.md.request.QueryLogsTreeRequest;
import com.md.response.AppInfoResponse;
import com.md.response.LogsResponse;
import com.md.response.LogsTreeResponse;
import com.md.response.QueryLogsResponse;
import com.md.response.SimplifyLogsTreeResponse;
import com.md.util.ClassUtils;
import com.md.util.CollectionUtil;
import com.md.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author 刘骄阳
 * 2022-09-24 1:35
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LogsApplicationService implements LogsApi, OpenLogsApi {
  private final LogsDomainService logsDomainService;
  private final LogsRepository logsRepository;
  private final SystemClient systemClient;

  @Override
  public CommonResult<LogsResponse> create(final OperationLogsRequest request) {
    LogsAssembler.checkCreateOperateLogRequest(request);
    try {
      return CommonResult.success(logsDomainService.createLogs(request));
    } catch (Exception e) {
      log.error("创建日志失败: {}", e.getMessage(), e);
      return CommonResult.error(ErrorEnum.CREATE_OPERATE_LOG_ERROR);
    }
  }

  @Override
  public CommonResult<LogsResponse> update(final OperationLogsRequest request) {
    LogsAssembler.checkCreateOperateLogRequest(request);
    try {
      return CommonResult.success(logsDomainService.updateLogs(request));
    } catch (Exception e) {
      log.error("更新日志失败: {}", e.getMessage(), e);
      return CommonResult.error(ErrorEnum.UPDATE_OPERATE_LOG_ERROR);
    }
  }

  /**
   * 分页查询
   *
   * @param request 请求实体
   * @return 操作结果
   */
  public CommonResult<QueryLogsResponse> selectPage(final QueryLogsRequest request) {
    QueryLogsBO queryLogsBO = LogsAssembler.buildQueryLogsRequest2BO(request);
    QueryLogsResponse response = new QueryLogsResponse();
    response.setPageNum(request.getPageNum());
    response.setPageSize(request.getPageSize());
    Logs logs = ClassUtils.source2Target(request, Logs.class);
    PageResponse<Logs> data = logsDomainService.selectRootLoByPage(queryLogsBO);
    List<Long> userIds = CollectionUtil.map(data.getData(), Logs::getCreateBy);
    Map<Long, AppInfoResponse> appInfoResponseMap =
      systemClient.getAppInfoResponseByIds(CollectionUtil.map(data.getData(), Logs::getAppInfoId));
//    List<InternalUsersResponse> usersResponses = authenticationClientService.selectUserListByIds(userIds);
//    Map<Long, String> userNameMap = CollectionUtil.toMap(usersResponses, InternalUsersResponse::getId,
//        InternalUsersResponse::getName);
    //数据
    response.setData(LogsAssembler.poToResponse(data.getData(), appInfoResponseMap, Maps.newHashMap()));
    //分页总页数
    response.setPages(data.getPages());
    //符合条件总数量
    response.setTotal(data.getTotal());
    // 游标
    response.setCursor(request.getCursor());
    return CommonResult.success(response);
  }

  /**
   * 查询请求链路
   *
   * @param request 请求实体
   * @return 操作结果
   */
  public CommonResult<LogsTreeResponse> selectTree(final QueryLogsTreeRequest request) {
    Logs node = logsDomainService.queryByDataId(request.getDataId());
    if (ObjectUtil.isEmpty(node)) {
      throw ServerException.build(ErrorEnum.LOGS_NOT_EXISTS);
    }
    AppInfoResponse appInfoResponse = OpenApiClient.queryAppInfo(node.getTenantId(), node.getBrandId());

    LogsTreeResponse response = LogsAssembler.poToTreeResponse(node, appInfoResponse);
    LogsTreeResponse children = logsDomainService.recursionChildrenLogs(request.getDataId());
    response.setChildren(children.getChildren());
    LogsTreeResponse parent = logsDomainService.recursionParentLogs(response.getParentId(), response);
    if (ObjectUtil.isEmpty(parent)) {
      return CommonResult.success(response);
    }
    return CommonResult.success(parent);
  }

  @Override
  public CommonResult<SimplifyLogsTreeResponse> selectTreeMap(final QueryLogsTreeRequest request) {
    Logs node = logsDomainService.queryByDataId(request.getDataId());
    if (ObjectUtil.isEmpty(node)) {
      throw ServerException.build(ErrorEnum.LOGS_NOT_EXISTS);
    }
    List<Logs> logsList = logsDomainService.queryByRootId(node.getRootId());
    AppInfoResponse appInfoResponse = OpenApiClient.queryAppInfo(node.getTenantId(), node.getBrandId());
    SimplifyLogsTreeResponse simplifyLogsTreeResponse =
      LogsAssembler.poToSimplifyLogsTreeResponse(logsList, appInfoResponse, request.getNeedMap());
    return CommonResult.success(simplifyLogsTreeResponse);
  }
}
